// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

import { time, timeEnd } from "console";
import { read } from "fs";
class cellsClass {
    text: string = ""
    indexNum: string = "";
    type: number = 0;
}
const { ccclass, property } = cc._decorator;
const GRID_WIDTH = 6;
const GRID_HEIGHT = 6;
const CELL_WIDTH = 70
const CELL_HEIGHT = 70
const GRID_PIXEL_WIDTH = GRID_WIDTH * CELL_WIDTH;
const GRID_PIXEL_HEIGHT = GRID_HEIGHT * CELL_HEIGHT;
@ccclass


export default class Grid extends cc.Component {


    @property(cc.Prefab)
    public item: cc.Prefab = null;

    private shuxiangChao = [];
    private henxiangChao = [];
    private cells: cellsClass[][] = [];
    private cellsNode: cc.Node[][] = [];
    private selectList = [];
    private posX: number = 100;
    private posY: number = -1;
    private wordLength: number = 0;
    private deletedNum: number = 0;
    private instantNum: number = 0;

    private isReset: boolean = false;

    private left: boolean = false;
    private right: boolean = false;
    private isInPlayAni: boolean = false;

    private indexNum: string = ""
    private type: number = 0;
    onLoad() {
        for (var i = 0; i < GRID_HEIGHT; i++) {
            this.cells[i] = [];
            this.cellsNode[i] = [];
            for (var j = 0; j < GRID_WIDTH; j++) {
                this.cells[i][j] = { text: "", indexNum: "", type: -1 };
                this.cellsNode[i][j] = null
            }
        }

        this.node.on(cc.Node.EventType.TOUCH_START, (eventTouch) => {
            if (this.isInPlayAni) {//播放动画中，不允许点击
                return true;
            }
            let touchLoc = eventTouch.getLocation();
            this.moreSelect(this.cellsNode, touchLoc)
            return true;
        }, this);
        // 滑动操作逻辑
        this.node.on(cc.Node.EventType.TOUCH_MOVE, (eventTouch) => {
            let touchLoc = eventTouch.getLocation();
            this.moreSelect(this.cellsNode, touchLoc)

        }, this);

        this.node.on(cc.Node.EventType.TOUCH_END, (eventTouch) => {
            if (this.checkAnswerForAll(this.selectList)) {
                this.isInPlayAni = true
                setTimeout(() => {
                    this.checkAnswer(this.selectList);
                }, 500);
            }
        }, this);

        this.node.on(cc.Node.EventType.TOUCH_CANCEL, (eventTouch) => {
            if (this.checkAnswerForAll(this.selectList)) {
                this.isInPlayAni = true;
                setTimeout(() => {
                    this.checkAnswer(this.selectList);
                }, 500);

            }
        })


        this.node.setContentSize(GRID_WIDTH * 70, GRID_HEIGHT * 70)

        this.init();
        // this.getNewUserList();
    }

    private moreSelect(cellNodes, touchLoc) {
        if (this.checkAnswerForAll(this.selectList)) {
            return
        }
        for (let k = cellNodes.length - 1; k >= 0; k--) {
            let box = cellNodes[k]
            for (let d = box.length - 1; d >= 0; d--) {
                if (box[d]) {
                    let box1 = box[d].getBoundingBoxToWorld();
                    if (box1.contains(touchLoc)) {
                        box[d].getChildByName("bg").color = cc.color(255, 0, 0)
                        if (!box[d].isSelect && (!this.checkAnswerForAll(this.selectList))) {
                            box[d].isSelect = true;
                            this.selectList.push(box[d]);
                        }
                    }
                }
            }
        }
    }

    /**判断所有答案 包括三字词  两字词 */
    private checkAnswerForAll(data) {
        if (data[0]) {
            let v = data[0]["type"]
            if (v && data.length == v) {
                return true
            }
        }
        return false
    }

    private checkAnswer(data) {

        let fail = (data) => {
            for (let i = data.length - 1; i >= 0; i--) {
                let node = data.pop();

                // let node = this.selectCell(va);
                node.getChildByName("bg").color = cc.color(255, 255, 255)
                node.isSelect = null;
            }
            this.isInPlayAni = false;
            console.log("选择错误！！")

            this.selectList = []
        }

        let success = (data, isX, isY) => {
            //消除  下落
            this.wordLength = data.length;
            for (let i = data.length - 1; i >= 0; i--) {
                let node = data.pop();
                this.cells[node.posx][node.posy].text = "";

                node.getChildByName("bg").color = cc.color(0, 255, 0)
                this.cellsNode[node.posx][node.posy] = null;
                cc.tween(node).to(0.2, { scaleX: 0, scaleY: 0 }).start();
                setTimeout(() => {
                    this.deletedNum++;
                    node.destroy();
                }, 300);
            }

            this.checkDown(isX, isY);

        }


        // let node = this.selectCell(data[0]);
        let node = data[0]
        let nx = node.posx;
        let ny = node.posy;
        let isX = true;
        let isY = true;
        this.posY = node.posy;
        this.posX = node.posx;
        for (let i = 1; i < data.length; i++) {


            if (data[i].posx < this.posX) {
                this.posX = data[i].posx;
            }
            if (this.posY < data[i].posy) {
                this.posY = data[i].posy
            }
            let node1 = data[i]

            if (nx != node1.posx) {
                isX = false;
            }
            if (ny != node1.posy) {
                isY = false;
            }

        }
        if (!isX && !isY) {
            fail(data);
            return
        }

        let index1 = node["indexNum"]
        let indexFail = false;
        for (let i = 1; i < data.length; i++) {
            let node1 = data[i];
            if (index1 != node1["indexNum"]) {
                indexFail = true;
                break;
            }
        }

        if (indexFail) {
            fail(data);
            return
        }

        success(data, isX, isY);
    }

    initList() {
        this.shuxiangChao = []
        for (let i = 0; i < GRID_HEIGHT; i++) {
            this.shuxiangChao.push(i);
        }
        this.henxiangChao = []
        for (let i = 0; i < GRID_WIDTH; i++) {
            this.henxiangChao.push(i);
        }

    }

    private reset() {
        for (var i = 0; i < GRID_HEIGHT; i++) {
            this.cells[i] = [];
            this.cellsNode[i] = [];
            for (var j = 0; j < GRID_WIDTH; j++) {
                this.cells[i][j] = { text: "", indexNum: "", type: -1 };
                this.cellsNode[i][j] = null;
            }
        }
    }


    /**新手引导 成语数据 */
    public getNewUserList() {
        const data = [["1", "1", "1", "1"], ["2", "2", "2", "2"], ["3", "3", "3", "3"]]
        this.reset();
        let newUserType = [{ fangxiang: "right", hard: 4 }, { fangxiang: "left", hard: 1 }, { fangxiang: "left", hard: 0 }]
        let r;
        for (let i = 0; i < data.length; i++) {
            if (newUserType[i]["fangxiang"] == "left") {
                this.left = true;
                this.right = false;
            } else {
                this.left = false;
                this.right = true;
            }
            this.initList();
            let f = (i) => {
                r = newUserType[i]["hard"]
                if (this.left) {
                    //横向
                    this.henxiangChao.push(newUserType[i]["hard"])
                    r = this.henxiangChao.pop();
                    console.log("横向几号", r)
                    let isOk = true;
                    if (isOk) {
                        //成功确认横向
                        this.addList("LR", r, data[i])
                    }
                } else if (this.right) {
                    //竖向
                    this.shuxiangChao.push(newUserType[i]["hard"])
                    r = this.shuxiangChao.pop();
                    console.log("竖向几号", r)

                    this.addList("UD", r, data[i])
                } else {
                    console.log("当前词组无位置加入", data[i][0]["text"])
                }
            }
            f(i);
            console.log(i)
        }

        console.log(this.cells);

        //渲染
        for (let i = 0; i < this.cells.length; i++) {

            for (let j = 0; j < this.cells[i].length; j++) {
                let item = cc.instantiate(this.item)
                item.setPosition(i * item.width - this.node.width / 2 + item.width / 2, j * item.height - this.node.height / 2 + item.height / 2)
                if (this.cells[i][j] && this.cells[i][j]["text"] != "") {
                    item.getChildByName("label").getComponent(cc.Label).string = this.cells[i][j]["text"] + ""
                } else {
                    item.active = false;
                }
                item["posx"] = i;
                item["posy"] = j;
                this.cellsNode[i][j] = item;
                this.node.addChild(item);
            }
        }
    }


    init() {
        console.time("开始");
        // const data = [["1", "1", "1", "1"], ["2", "2", "2", "2"], ["3", "3"], ["4", "4", "4"], ["5", "5", "5", "5"], ["6", "6", "6", "6"], ["7", "7", "7", "7"], ["8", "8", "8", "8"]]
        let dataLength = [];
        const data = [[{ text: "三" }, { text: "心" }, { text: "二" }, { text: "意" }], [{ text: "六" }, { text: "六" }, { text: "大" }, { text: "顺" }], [{ text: "五" }, { text: "福" }, { text: "临" }, { text: "门" }]]
        this.reset();

        let r;

        for (let i = 0; i < data.length; i++) {
            // dataLength.push(data[i].length);
            this.indexNum = `a${i}`
            this.type = data[i].length

            let index = 0;
            if (i == 0) {
                this.left = true;
                index = 0.6;
            } else if (i == 1) {
                this.left = false;
                index = 0.1
            }
            this.left = true;
            this.right = true;
            this.initList();
            let f = (fangxiang = 0) => {


                r = Math.random();
                if (fangxiang != 0) {
                    r = fangxiang
                }
                if (r > 0.5 && this.left) {
                    //横向

                    this.henxiangChao = this.shuffle(this.henxiangChao);
                    r = this.henxiangChao.pop();
                    console.log("横向几号1", r)
                    while ((r || r == 0) && r + data[i].length > GRID_WIDTH) {
                        //超过横向
                        r = this.henxiangChao.pop();
                        console.log("横向取出r", r)
                    }

                    if (!(r || r == 0)) {

                        if (this.henxiangChao.length == 0) {
                            this.left = false;
                            console.log("重新开始")
                            f(0.1)
                        }
                        return
                    }

                    console.log("横向几号2", r)
                    let isOk = true;
                    for (let j = r; j < r + data[i].length; j++) {
                        if (!this.searchList(j)) {
                            isOk = false;
                            break;
                        }
                    }

                    if (isOk) {
                        //成功确认横向
                        this.addList("LR", r, data[i])
                    } else {
                        if (this.henxiangChao.length == 0) {
                            console.log("重新开始")

                            this.left = false;
                            f(0.1)
                            //重新确认方向
                        } else {

                            console.log("重新开始左")

                            f(0.6)
                        }
                    }

                } else if (this.right && r <= 0.5) {
                    //竖向

                    this.shuxiangChao = this.shuffle(this.shuxiangChao)
                    r = this.shuxiangChao.pop();
                    console.log("竖向几号1", r)
                    let height = this.searchHeight(r)
                    console.log("第一次height", height)
                    while (((r != null && height != null && height + data[i].length > GRID_HEIGHT) || !this.searchLow(r)) || (height == null && this.shuxiangChao.length > 0)) {
                        //超过顶
                        r = this.shuxiangChao.pop();

                        height = this.searchHeight(r)
                        console.log("竖向取出r", r, height)
                    }

                    console.log("竖向几号2", r, height)

                    if (!(r || r == 0) || !(height || height == 0)) {
                        this.right = false;
                        console.log("重新开始")
                        f(0.6)
                        return
                    }
                    this.addList("UD", r, data[i])
                } else {
                    console.log("当前数字无位置加入", data[i][0].text)
                    this.isReset = true;

                    return
                }
            }
            f(index);
            if (this.isReset) {
                break;
            }
            console.log(i)
        }

        console.timeEnd("开始");

        if (this.isReset) {
            this.isReset = false;
            return this.init();
        }
        console.log("list")
        console.log(this.cells);

        //渲染
        for (let i = 0; i < this.cells.length; i++) {
            for (let j = 0; j < this.cells[i].length; j++) {
                let item = cc.instantiate(this.item)
                item.setPosition(i * item.width - this.node.width / 2 + item.width / 2, j * item.height - this.node.height / 2 + item.height / 2)
                if (this.cells[i][j] && this.cells[i][j]["text"] != "") {
                    this.instantNum++;
                    item.getChildByName("label").getComponent(cc.Label).string = this.cells[i][j]["text"] + ""
                } else {
                    item.active = false;
                }
                item["indexNum"] = this.cells[i][j]["indexNum"]
                item["type"] = this.cells[i][j]["type"]
                item["posx"] = i;
                item["posy"] = j;
                this.cellsNode[i][j] = item;
                this.node.addChild(item);
            }
        }

    }

    private checkDown(isX, isY) {

        let finish = () => {
            this.isInPlayAni = false;
        }
        if (isY) {
            //横向消除
            for (let i = 0; i < this.wordLength; i++) {
                for (let j = 1; j < GRID_HEIGHT - this.posY; j++) {
                    if (this.cells[this.posX + i][this.posY + j]?.text == "") {
                        continue
                    }
                    cc.tween(this.cellsNode[this.posX + i][this.posY + j]).by(0.3, { y: -70 }).start();
                    this.cellsNode[this.posX + i][this.posY + j]["posx"] = this.posX + i
                    this.cellsNode[this.posX + i][this.posY + j]["posy"] = this.posY + j - 1
                    let temp = this.cellsNode[this.posX + i][this.posY + j]
                    this.cellsNode[this.posX + i][this.posY + j - 1] = temp
                    this.cellsNode[this.posX + i][this.posY + j] = null;
                    let temp1 = this.cells[this.posX + i][this.posY + j]
                    this.cells[this.posX + i][this.posY + j - 1] = temp1
                    this.cells[this.posX + i][this.posY + j]["text"] = "";
                }
            }
            finish();

        }
        if (isX) {
            //竖向消除
            for (let j = 1; j < GRID_HEIGHT - this.posY; j++) {
                if (this.cells[this.posX][this.posY + j]?.text == "") {
                    continue
                }
                cc.tween(this.cellsNode[this.posX][this.posY + j]).by(0.3, { y: -70 * this.wordLength }).start();
                this.cellsNode[this.posX][this.posY + j]["posx"] = this.posX
                this.cellsNode[this.posX][this.posY + j]["posy"] = this.posY + j - this.wordLength
                let temp = this.cellsNode[this.posX][this.posY + j]
                this.cellsNode[this.posX][this.posY + j - this.wordLength] = temp
                this.cellsNode[this.posX][this.posY + j] = null;
                let temp1 = this.cells[this.posX][this.posY + j]
                this.cells[this.posX][this.posY + j - this.wordLength] = temp1
                this.cells[this.posX][this.posY + j]["text"] = ""
            }
            finish();
        }

    }

    private convertTouchPosToCell(pos) {
        pos = this.node.convertToNodeSpace(pos);
        if (pos.x < 0 || pos.x >= GRID_PIXEL_WIDTH || pos.y < 0 || pos.y >= GRID_PIXEL_HEIGHT) {
            return false;
        }
        var x = Math.floor(pos.x / CELL_WIDTH);
        var y = Math.floor(pos.y / CELL_HEIGHT);

        return cc.v2(x, y);
    }

    private shuffle(arr) {
        let i = arr.length;
        while (i) {
            let j = Math.floor(Math.random() * i--);
            [arr[j], arr[i]] = [arr[i], arr[j]];
        }
        return arr;
    }

    /**
     * 
     * @param fangxiang 方向 LR OR  UD
     * @param num 词组多长
     */
    private addList(fangxiang, list, data) {
        if (fangxiang == "LR") {

            for (let i = 0; i < data.length; i++) {
                let h = this.searchHeight(list);
                data[i].indexNum = this.indexNum;
                data[i].type = this.type;
                this.cells[list][h] = data[i]
                list++;
                console.log(`w:${list} h:${h}  value: ${data[i].text}`)
            }
        } else {
            let h = this.searchHeight(list);
            for (let i = 0; i < data.length; i++) {
                data[i].indexNum = this.indexNum;
                data[i].type = this.type;
                this.cells[list][h] = data[i]
                h += 1;
                console.log(`w:${list} h:${h}  value: ${data[i].text}`)
            }
        }


    }

    private searchList(h) {
        let isOk = true;
        for (let i = h; i < GRID_WIDTH; i++) {
            if (this.cells[i][GRID_HEIGHT - 1] && this.cells[i][GRID_HEIGHT - 1]["text"] != "") {
                isOk = false;
                break;
            }
        }
        return isOk
    }

    private searchHeight(w) {
        let value = null;
        try {

            for (let i = 0; i < GRID_HEIGHT; i++) {
                if (this.cells[w][i] && this.cells[w][i]["text"] == "") {
                    // return i
                    value = i;
                    break;
                }
            }
        } catch {

        }
        if (value == null) {
            console.log("w    ", w)
        }


        return value;
    }

    private searchLow(r) {
        let left = false;
        let right = false;

        if (this.cells[r - 1] && this.cells[r - 1][0] && this.cells[r - 1][0]["text"] != "") {
            left = true;
        }
        if (this.cells[r + 1] && this.cells[r + 1][0] && this.cells[r + 1][0]["text"] != "") {
            right = true;
        }
        // if (r == 0) {
        //     left = false;
        // }
        // if (r == this.GRID_WIDTH) {
        //     right = false;
        // }
        if (!left && !right) {
            console.log(`r: ${r}  左右空  重新来`)
        }

        return left || right
    }

    private selectCell(pos: cc.Vec2): cc.Node {
        if (cc.isValid(this.cellsNode[pos.x][pos.y])) {
            return this.cellsNode[pos.x][pos.y]
        }
    }

    update() {
        //重新开始
        if (this.deletedNum >= this.instantNum) {
            this.deletedNum = 0;
            this.instantNum = 0;
            this.init();
        }
    }
}

/**生成从minNum到maxNum的随机数 */
export function randomNum(minNum: number, maxNum: number): number {
    switch (arguments.length) {
        case 1:
            return parseInt(`${Math.random() * minNum + 1}`, 10);
        case 2:
            return parseInt(
                `${Math.random() * (maxNum - minNum + 1) + minNum}`,
                10
            );
        default:
            return 0;
    }
}



